package com.tsd.jxc.buy.service.impl;

import com.tsd.base.service.BaseCodeRuleService;
import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.constants.Constants;
import com.tsd.core.constants.VersionConstants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.service.GetDuplicatedObj;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.ErrorCode;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.HttpResult;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.buy.dao.JxcBuyReturnBillDetailMapper;
import com.tsd.jxc.buy.dao.JxcBuyReturnBillMapper;
import com.tsd.jxc.buy.entity.JxcBuyReturnBill;
import com.tsd.jxc.buy.entity.JxcBuyReturnBillDetailExt;
import com.tsd.jxc.buy.entity.JxcBuyReturnBillExt;
import com.tsd.jxc.buy.service.JxcBuyOrderDetailService;
import com.tsd.jxc.buy.service.JxcBuyReturnBillDetailService;
import com.tsd.jxc.buy.service.JxcBuyReturnBillService;
import com.tsd.jxc.config.JxcCodeRuleConstants;
import com.tsd.jxc.fin.FinanceConstants;
import com.tsd.jxc.fin.dao.JxcFinanceAccountDetailMapper;
import com.tsd.jxc.fin.dao.JxcFinanceAccountMapper;
import com.tsd.jxc.fin.entity.JxcFinanceAccountDetailExt;
import com.tsd.jxc.fin.entity.JxcFinanceAccountExt;
import com.tsd.jxc.fin.job.JxcFinanceJob;
import com.tsd.jxc.stock.StockConstants;
import com.tsd.jxc.stock.entity.JxcStockOutbillExt;
import com.tsd.jxc.stock.entity.JxcStockOutbillItemExt;
import com.tsd.jxc.stock.service.JxcStockGoodsService;
import com.tsd.jxc.stock.service.JxcStockOutbillService;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import com.tsd.system.entity.SysUserExt;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;

/**
 * 描述：JxcBuyReturnBill 服务实现层
 *
 * @author Hillpool
 * @date 2022/07/29 15:00:45
 */
@Service
public class JxcBuyReturnBillServiceImpl extends BaseServiceImpl implements JxcBuyReturnBillService, GetDuplicatedObj {

    @Resource
    private JxcBuyReturnBillMapper jxcBuyReturnBillMapper;
    @Resource
    private JxcBuyReturnBillDetailMapper jxcBuyReturnBillDetailMapper;
    @Resource
    private JxcFinanceAccountMapper jxcFinanceAccountMapper;
    @Resource
    private JxcFinanceAccountDetailMapper jxcFinanceAccountDetailMapper;
    @Resource
    private BaseCodeRuleService baseCodeRuleService;
    @Resource
    private JxcBuyReturnBillDetailService jxcBuyReturnBillDetailService;
    @Resource
    private JxcBuyOrderDetailService jxcBuyOrderDetailService;
    @Resource
    private JxcStockOutbillService jxcStockOutbillService;
    @Resource
    private JxcFinanceJob jxcFinanceJob;
    @Resource
    private JxcStockGoodsService jxcStockGoodsService;

    @Override
    public JxcBuyReturnBill getJxcBuyReturnBillById(Long id) throws Exception {
        return jxcBuyReturnBillMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcBuyReturnBillExt queryBySid(String sid) throws Exception {
        JxcBuyReturnBillExt billExt = jxcBuyReturnBillMapper.selectBySid(sid);
        if (billExt != null) {
            List<JxcBuyReturnBillDetailExt> detailExtList = jxcBuyReturnBillDetailService.queryValidByReturnList(Collections.singletonList(billExt.getSid()));
            billExt.setDetail_list(detailExtList);
        }
        return billExt;
    }

    @Override
    public void deleteJxcBuyReturnBills(List<String> list, SysUser opUser) throws Exception {
        if (HlpUtils.isEmptyList(list)) {
            return;
        }
        BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
        logicVo.setSidList(list);
        jxcBuyReturnBillMapper.deleteLogicBySidList(logicVo);
        // 删除明细
        jxcBuyReturnBillDetailMapper.deleteLogicByReturnList(logicVo);
        // 更新采购订单及明细
        jxcBuyReturnBillDetailService.undateReturn2BuyOrder(list);
    }

    @Override
    public boolean isDuplicated(Object obj, String code) {
        if (obj == null) {
            return false;
        }
        JxcBuyReturnBillExt billExt = (JxcBuyReturnBillExt) obj;
        billExt.setCode(code);
        return jxcBuyReturnBillMapper.selectDuplicatedCode(billExt) != null;
    }

    @Override
    public void saveJxcBuyReturnBill(JxcBuyReturnBillExt record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            super.checkEmpty(record.getSupplier_sid(), "请提供参数：supplier_sid");
            if (!HlpUtils.isEmpty(record.getCode())) {
                //如果是手动设置了编号，则检查是否有相同的，有的话，置空后重新生成
                JxcBuyReturnBillExt same = jxcBuyReturnBillMapper.selectDuplicatedCode(record);
                if (same != null) {
                    record.setCode(null);
                }
            }
            String genCode = baseCodeRuleService.genCode(record.getSupplier_sid(), JxcCodeRuleConstants.TYPE_JXC_BUY_RETURN_BILL, JxcCodeRuleConstants.TYPE_NAME_JXC_BUY_RETURN_BILL, opUser, record.getCode(), record, this);
            record.setCode(genCode);
            record.setState(Constants.VALUE_NO);
            record.setAudit_state(Constants.VALUE_NO);
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE, new Date(), record.getReturn_date());
            jxcBuyReturnBillMapper.insertSelective(record);
        } else {
            JxcBuyReturnBillExt same = jxcBuyReturnBillMapper.selectDuplicatedCode(record);
            if (same != null) {
                throw new HlpException("已存在相同编号的退货单");
            }
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            super.updateYyyyMmdd(record, record.getReturn_date());
            jxcBuyReturnBillMapper.updateByPrimaryKeySelective(record);
        }
        jxcBuyReturnBillDetailService.saveJxcBuyReturnBillDetail(record, opUser);
    }

    @Override
    public List<JxcBuyReturnBillExt> findJxcBuyReturnBills(Map<String, Object> params, PageBean page) throws Exception {
        return jxcBuyReturnBillMapper.selectByPage(params, page);
    }

    @Override
    public List<JxcBuyReturnBillExt> findJxcBuyReturnBills(Map<String, Object> params) throws Exception {
        return jxcBuyReturnBillMapper.selectByParams(params);
    }

    @Override
    public HttpResult<String> changeJxcBuyReturnBillAuditState(List<String> sidList, Integer state, SysUserExt opUser) throws Exception {
        JxcBuyReturnBillExt params = new JxcBuyReturnBillExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcBuyReturnBillExt> billExtList = jxcBuyReturnBillMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(billExtList)) {
            return HttpResult.fail(ErrorCode.CODE_PROC_ERROR, "退货单信息为空");
        }

        if (state == 1) {
            List<JxcBuyReturnBillDetailExt> detailExts = jxcBuyReturnBillDetailMapper.selectOverReturn(sidList);
            if (!HlpUtils.isEmptyList(detailExts)) {
                List<String> nameList = ListUtil.map(detailExts, JxcBuyReturnBillDetailExt::getName);
                String msg = StringUtils.join(nameList, "、") + " 总退货数量大于采购数量";
                return HttpResult.fail(ErrorCode.CODE_PROC_ERROR, msg);
            }
        }

        boolean isFree = VersionConstants.accountSetVersionIsFree();
        for (JxcBuyReturnBillExt billExt : billExtList) {
            if (state == 1) {
                billExt.setAudit_state(Constants.VALUE_YES);
                billExt.setAuditor_sid(opUser.getSid());
                billExt.setAuditor_name(opUser.getName());
                billExt.setAudit_date(new Date());
                if (isFree) {
                    jxcStockGoodsService.updateByBuyReturnBill(Constants.OP_SUB, billExt);
                }
            } else if (state == -1) {
                billExt.setAudit_state(Constants.VALUE_NO);
                billExt.setAuditor_sid(null);
                billExt.setAuditor_name(null);
                billExt.setAudit_date(null);
                if (isFree) {
                    jxcStockGoodsService.updateByBuyReturnBill(Constants.OP_ADD, billExt);
                }
            }
            jxcBuyReturnBillMapper.updateByPrimaryKey(billExt);
        }
        // 批量更新采购订单及明细
        List<String> returnList = ListUtil.map(billExtList, JxcBuyReturnBillExt::getSid);
        jxcBuyReturnBillDetailService.undateReturn2BuyOrder(returnList);
        return HttpResult.success(null);
    }

//    /**
//     * 检查退货数量是否超出采购数量
//     *
//     * @param billExtList
//     * @throws Exception
//     */
//    private void checkReturn(List<JxcBuyReturnBillExt> billExtList) throws Exception {
//        List<String> returnList = ListUtil.map(billExtList, JxcBuyReturnBillExt::getSid);
//        List<JxcBuyReturnBillDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(returnList, list -> jxcBuyReturnBillDetailService.queryValidByReturnList(list));
//        if (HlpUtils.isEmptyList(detailExtList)) {
//            return;
//        }
//        List<String> buyDetailList = ListUtil.map(detailExtList, JxcBuyReturnBillDetailExt::getBuy_detail_sid);
//        List<JxcBuyOrderDetailExt> orderDetailExtList = ThreadPoolTaskUtil.queryInList4Split(buyDetailList, list -> jxcBuyOrderDetailService.queryValidBySidList(list));
//        if (HlpUtils.isEmptyList(orderDetailExtList)) {
//            return;
//        }
//        for (JxcBuyOrderDetailExt detailExt : orderDetailExtList) {
//            List<JxcBuyReturnBillDetailExt> filter = ListUtil.filter(detailExtList, t -> t.getBuy_detail_sid().equals(detailExt.getSid()));
//            if (HlpUtils.isEmptyList(filter)) {
//                continue;
//            }
//            double totalReturn = 0D;
//            for (JxcBuyReturnBillDetailExt ext : filter) {
//                totalReturn = DoubleUtil.add(totalReturn, ext.getQty());
//            }
//            if (!HlpUtils.isEmpty(detailExt.getReturn_qty())) {
//                totalReturn = DoubleUtil.add(totalReturn, detailExt.getReturn_qty());
//            }
//            double value = DoubleUtil.sub(detailExt.getQty(), totalReturn);
//            if (value < 0) {
//                List<String> codeList = ListUtil.map(filter, JxcBuyReturnBillDetailExt::getOrder_code);
//                List<String> goodsList = ListUtil.map(filter, t -> t.getGoods_name() + " / " + t.getSpec_name());
//                throw new HlpException("退货单：" + StringUtils.join(codeList, "、") + " " + StringUtils.join(goodsList, "、") + " 总退货数量大于采购数量");
//            }
//        }
//    }

    @Override
    public void genJxcBuyReturnBill2OutBill(List<String> sidList, SysUserExt opUser) throws Exception {
        List<JxcBuyReturnBillExt> billExtList = ThreadPoolTaskUtil.queryInList4Split(sidList, list -> {
            JxcBuyReturnBillExt params = new JxcBuyReturnBillExt();
            params.setDr(0);
            params.setSid_list(list);
            return jxcBuyReturnBillMapper.selectByEntity(params);
        });
        billExtList = ListUtil.filter(billExtList, t -> !StockConstants.IN_OUT_BILL_ALL.equals(t.getOut_bill()));
        if (HlpUtils.isEmptyList(billExtList)) {
            return;
        }
        List<String> billList = ListUtil.map(billExtList, JxcBuyReturnBillExt::getSid);
        List<JxcBuyReturnBillDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(billList, list -> jxcBuyReturnBillDetailService.queryValidByReturnList(list));
        if (HlpUtils.isEmptyList(detailExtList)) {
            return;
        }
        String storeWare_sid = null;
        List<JxcBuyReturnBillExt> updateList = new ArrayList<>();
        List<JxcBuyReturnBillDetailExt> updateDetailList = new ArrayList<>();
        for (JxcBuyReturnBillExt billExt : billExtList) {
            List<JxcBuyReturnBillDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getReturn_sid().equals(billExt.getSid()));
            if (HlpUtils.isEmptyList(filterList)) {
                continue;
            }
            billExt.setDetail_list(filterList);
            JxcStockOutbillExt outBillExt = billExt.genOutBill(storeWare_sid);
            if (HlpUtils.isEmptyList(outBillExt.getItem_list())) {
                continue;
            }
            jxcStockOutbillService.saveJxcStockOutbill(outBillExt, opUser);

            billExt.setOut_bill(StockConstants.IN_OUT_BILL_ALL);
            billExt.setOut_bill_sid(outBillExt.getSid());
            super.autoInjectBaseData(billExt, opUser, this.TYPE_UPDATE);
            updateList.add(billExt);

            for (JxcBuyReturnBillDetailExt detailExt : filterList) {
                detailExt.setOut_bill(StockConstants.DETAIL_IN_OUT_BILL_ALL);
                JxcStockOutbillItemExt itemExt = ListUtil.get(outBillExt.getItem_list(), t -> t.getGoods_sid().equals(detailExt.getGoods_sid()));
                if (itemExt != null) {
                    detailExt.setOut_bill_item_sid(itemExt.getSid());
                }
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_UPDATE);
                updateDetailList.add(detailExt);
            }
        }
        if (!HlpUtils.isEmptyList(updateList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcBuyReturnBillMapper.updateList(itemList));
        }
        if (!HlpUtils.isEmptyList(updateDetailList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateDetailList, false, itemList -> jxcBuyReturnBillDetailMapper.updateList(itemList));
        }
    }

    @Override
    public Integer genJxcFinanceAccountDetail4BuyReturn(List<String> sidList, SysUserExt opUser) throws Exception {
        JxcBuyReturnBillExt params = new JxcBuyReturnBillExt();
        params.setDr(0);
        params.setSid_list(sidList);
        List<JxcBuyReturnBillExt> billExtList = jxcBuyReturnBillMapper.selectByEntity(params);
        if (HlpUtils.isEmptyList(billExtList)) {
            return 0;
        }
        List<JxcBuyReturnBillExt> filterList = ListUtil.filter(billExtList, t -> !HlpUtils.isEmpty(t.getGen_finance()) && t.getGen_finance() == 1);
        if (!HlpUtils.isEmptyList(filterList)) {
            List<String> codeList = ListUtil.map(billExtList, JxcBuyReturnBillExt::getCode);
            throw new HlpException("采购退货单：" + StringUtils.join(codeList, "、") + " 已生成对账！");
        }

        List<String> supplierList = ListUtil.map(billExtList, JxcBuyReturnBillExt::getSupplier_sid);
        // 查询账户余额
        List<JxcFinanceAccountExt> accountExtList = jxcFinanceAccountMapper.selectValidByPartyList(supplierList);
        Map<String, Double> remainAmountMap = new HashMap<>();
        List<JxcBuyReturnBillExt> updateList = new ArrayList<>();
        List<JxcFinanceAccountDetailExt> list = new ArrayList<>();
        String dataSource = DataSourceContextHolder.getDataSourceType();
        for (JxcBuyReturnBillExt billExt : billExtList) {
            JxcFinanceAccountExt accountExt = ListUtil.get(accountExtList, t -> t.getRelated_party_sid().equals(billExt.getSupplier_sid()));
            List<JxcFinanceAccountDetailExt> detailExtList = billExt.genAccountDetail();
            if (!HlpUtils.isEmptyList(detailExtList)) {
                for (JxcFinanceAccountDetailExt detailExt : detailExtList) {
                    super.autoInjectBaseData(detailExt, opUser, this.TYPE_CREATE);
                    double remainAmount = 0D;
                    if (remainAmountMap.containsKey(billExt.getSupplier_sid())) {
                        remainAmount = remainAmountMap.get(billExt.getSupplier_sid());
                    } else if (accountExt != null) {
                        remainAmount = accountExt.getAmount().doubleValue();
                    }
                    if (FinanceConstants.OP_ADD.equals(FinanceConstants.getAccountTypeOp(dataSource, detailExt.getBill_type()))) {
                        remainAmount = DoubleUtil.add(remainAmount, FinanceConstants.getAmount(detailExt));
                    } else {
                        remainAmount = DoubleUtil.sub(remainAmount, FinanceConstants.getAmount(detailExt));
                    }
                    remainAmountMap.put(billExt.getSupplier_sid(), remainAmount);
                    detailExt.setRemain_amount(BigDecimal.valueOf(remainAmount));
                    String genCode = baseCodeRuleService.genCode(detailExt.getRelated_party_sid(), JxcCodeRuleConstants.TYPE_JXC_FINANCE_ACCOUNT, JxcCodeRuleConstants.TYPE_NAME_JXC_FINANCE_ACCOUNT, opUser, null, null, null);
                    detailExt.setCode(genCode);
                    list.add(detailExt);
                }
            }

            JxcBuyReturnBillExt updateData = new JxcBuyReturnBillExt();
            updateData.setId(billExt.getId());
            updateData.setSid(billExt.getSid());
            updateData.setGen_finance(1);
            super.autoInjectBaseData(updateData, opUser, this.TYPE_UPDATE);
            updateList.add(updateData);
        }

        ThreadPoolTaskUtil.executeInList4Split(list, false, itemList -> jxcFinanceAccountDetailMapper.insertList(itemList));

        // 更新字段：gen_finance
        ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcBuyReturnBillMapper.updateList(itemList));

        // 添加队列
        for (JxcFinanceAccountDetailExt detailExt : list) {
            jxcFinanceJob.addJxcFinanceQue(FinanceConstants.QUEUE_OP_INSERT, FinanceConstants.BIZ_NAME_FINANCE, "updateFinanceAmount", detailExt.getId(), opUser);
        }
        return list.size();
    }

    @Override
    public List<JxcBuyReturnBillExt> findJxcBuyReturnBillsInclude(Map<String, Object> params, PageBean page) {
        return jxcBuyReturnBillMapper.selectBuyReturnBillsIncludeByPage(params, page);
    }

    @Override
    public List<JxcBuyReturnBillExt> queryJxcBuyReturnBillData4Print(List<String> sidList) throws Exception {
        List<JxcBuyReturnBillExt> list = ThreadPoolTaskUtil.queryInList4Split(sidList, itemList -> {
            JxcBuyReturnBillExt params = new JxcBuyReturnBillExt();
            params.setDr(0);
            params.setSid_list(itemList);
            return jxcBuyReturnBillMapper.selectByEntity(params);
        });
        if (!HlpUtils.isEmptyList(list)) {
            List<String> returnList = ListUtil.map(list, JxcBuyReturnBillExt::getSid);
            List<JxcBuyReturnBillDetailExt> detailExtList = jxcBuyReturnBillDetailService.queryValidByReturnList(returnList);
            for (JxcBuyReturnBillExt billExt : list) {
                List<JxcBuyReturnBillDetailExt> filterList = ListUtil.filter(detailExtList, t -> t.getReturn_sid().equals(billExt.getSid()));
                billExt.setDetail_list(filterList);
            }
        }
        return list;
    }
}
